﻿using System;
using System.ServiceModel;
using Framework.Core;
using Framework.Core.Io;
using Framework.Remoting.Conventions;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Wcf.Conventions
{
    internal interface IPouet
    {
    }

    public class WcfServiceInfoFactoryTest
    {
        private readonly IWcfServiceInfoFactory target;

        private readonly IConfigurationManagerAdapter configurationManagerAdapterMock;
        private readonly IBindingFactory bindingFactoryMock;
        private readonly IProtocolFactory protocolFactoryMock;
        private readonly MockRepository mockRepository = new MockRepository();

        public WcfServiceInfoFactoryTest()
        {
            configurationManagerAdapterMock = mockRepository.StrictMock<IConfigurationManagerAdapter>();
            bindingFactoryMock = mockRepository.StrictMock<IBindingFactory>();
            protocolFactoryMock = mockRepository.StrictMock<IProtocolFactory>();
            environmentsMock = mockRepository.StrictMock<IEnvironments>();
            environmentMock = mockRepository.StrictMock<IEnvironment>();
            target = new WcfServiceInfoFactory(configurationManagerAdapterMock, bindingFactoryMock, protocolFactoryMock);
        }

        private readonly IEnvironments environmentsMock;

        private readonly IEnvironment environmentMock;

        [Fact]
        public void When_Host_Convention_is_configured_Then_WcfServiceInfo_is_created()
        {
            MockConventions();

            mockRepository.ReplayAll();
            AssertIPouetWcfServiceInfo(target.Create(EnvMode.Prod, typeof (IPouet)));
            mockRepository.VerifyAll();
        }

        [Fact]
        public void When_Client_Convention_is_configured_Then_WcfServiceInfo_is_created()
        {
            MockConventions();
            mockRepository.ReplayAll();
            AssertIPouetWcfServiceInfo(target.Create<IPouet>(EnvMode.Prod));
            mockRepository.VerifyAll();
        }

        private static void AssertIPouetWcfServiceInfo(WcfServiceInfo actual)
        {
            Assert.Equal(new Uri("net.tcp://localhost:10300/Prod/Framework.Tests.Wcf.Conventions.IPouet/"), actual.Uri);
            Assert.True(actual.Binding is NetTcpBinding);
        }

        private void MockConventions()
        {
            configurationManagerAdapterMock
                .Expect(x => x.GetSection<IEnvironments, HostConfiguration>())
                .Return(environmentsMock);

            environmentsMock
                .Expect(x => x.GetEnvironment(EnvMode.Prod))
                .Return(environmentMock);

            environmentMock.Expect(x => x.BindingType).Return("netTcpBinding");

            var bindingMock = new NetTcpBinding();

            bindingFactoryMock.Expect(x => x.Create("netTcpBinding")).Return(bindingMock);
            protocolFactoryMock.Expect(x => x.Create(bindingMock)).Return("net.tcp");
            environmentMock.Expect(x => x.Host).Return("localhost");
            environmentMock.Expect(x => x.Port).Return(10300);
        }
    }
}